package com.richard.library.basic.basic;

import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;

import androidx.annotation.FloatRange;
import androidx.annotation.IdRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.appcompat.app.AppCompatDialogFragment;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import com.richard.library.basic.R;
import com.richard.library.basic.basic.dict.Direction;
import com.richard.library.basic.basic.uiview.UIView;
import com.richard.library.basic.basic.uiview.UIViewImpl;
import com.richard.library.basic.eventbus.EventData;
import com.richard.library.basic.util.DensityUtil;
import com.richard.library.basic.util.FragmentUtil;
import com.richard.library.basic.util.ViewUtil;
import com.richard.library.basic.widget.NavigationBar;
import com.richard.library.basic.widget.PlaceHolderView;
import com.richard.library.context.AppContext;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.List;

/**
 * <pre>
 * Description : BaseDialogFragment基类
 * Author : admin-richard
 * Date : 2019-05-10 17:57
 * Changelog:
 * Version            Date            Author              Detail
 * ----------------------------------------------------------------------
 * 1.0         2019-05-10 17:57      admin-richard         new file.
 * </pre>
 */
public abstract class BasicDialogFragment extends AppCompatDialogFragment implements UIInitializer {

    private UIView mUIView;
    protected NavigationBar navigationbar;
    //布局根视图
    private LinearLayout rootView;
    //布局文件ID
    private int layoutId;
    //布局内容视图
    private View contentView;

    private PlaceHolderView mPlaceHolderView;
    private DialogInterface.OnDismissListener mOnDismissListener;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(DialogFragment.STYLE_NO_TITLE, R.style.prompt_dialog_round_corner);
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (rootView != null) {
            return rootView;
        }

        this.initLayoutView();

        if (contentView == null) {
            contentView = inflater.inflate(layoutId, null);
        }

        rootView = new LinearLayout(getContext());
        rootView.setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT
                , ViewGroup.LayoutParams.MATCH_PARENT
        ));
        rootView.setId(R.id.basic_content_root);
        rootView.setOrientation(LinearLayout.VERTICAL);

        navigationbar = new NavigationBar(getContext());
        navigationbar.setVisibility(View.GONE);
        rootView.addView(navigationbar, new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT
                , AppContext.getDimensionPixelSize(R.dimen.navigation_bar_height)
        ));

        //更新子View大小
        if (contentView != null) {
            ViewGroup.LayoutParams childLayoutParams = contentView.getLayoutParams();
            if (childLayoutParams == null) {
                rootView.addView(contentView, new ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT
                        , ViewGroup.LayoutParams.MATCH_PARENT
                ));
            } else {
                childLayoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
                childLayoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
                rootView.addView(contentView);
            }
        }

        return rootView;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        this.initNavigation();
        mUIView = new UIViewImpl(getContext());

        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }

        this.initData();
        this.bindListener();
    }

    @Override
    public void onResume() {
        super.onResume();
        this.onUserVisible(isUserVisible());
    }

    @Override
    public void onPause() {
        super.onPause();
        this.onUserVisible(isUserVisible());
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        this.onUserVisible(isUserVisible());
        this.handleUserVisible();
    }

    @Override
    public void onDestroy() {
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
        if (mUIView != null) {
            mUIView.dismissLoading();
            mUIView.dismissMsgDialog();
            mUIView = null;
        }

        navigationbar = null;
        rootView = null;
        contentView = null;
        mPlaceHolderView = null;
        mOnDismissListener = null;
        super.onDestroy();
    }

    /**
     * 处理对用户的可见性
     */
    void handleUserVisible() {
        List<Fragment> fragment = FragmentUtil.getFragments(getChildFragmentManager());
        for (Fragment item : fragment) {
            if (item instanceof BasicFragment) {
                BasicFragment f = ((BasicFragment) item);
                f.onUserVisible(isUserVisible());
                f.handleUserVisible();
            } else if (item instanceof BasicDialogFragment) {
                BasicDialogFragment f = ((BasicDialogFragment) item);
                f.onUserVisible(isUserVisible());
                f.handleUserVisible();
            }
        }
    }

    /**
     * 当前fragment对用户是否可见
     */
    public boolean isUserVisible() {
        if (!isResumed()) {
            return false;
        }

        Fragment fragment = getParentFragment();
        if (fragment == null) {
            return !isHidden();
        }

        while (true) {
            Fragment f = fragment.getParentFragment();
            if (f == null) {
                return !fragment.isHidden();
            }
            fragment = f;
        }
    }

    /**
     * 初始化导航条
     */
    private void initNavigation() {
        if (navigationbar == null) {
            return;
        }
        navigationbar.setVisibility(View.VISIBLE);
        navigationbar.setRadius(
                getResources().getDimensionPixelSize(R.dimen.radius_value)
                , getResources().getDimensionPixelSize(R.dimen.radius_value)
                , 0
                , 0
        );
        navigationbar.setXBackgroundColor(getResources().getColor(R.color.navigation_bar_backcolor));

        navigationbar.setBottomLineViewShow(false);
        navigationbar.setRightImageView(R.mipmap.icon_close);
        navigationbar.setRightImageViewShow(true);
        navigationbar.setRightImageViewClickListener((v) -> {
            if (getDialog() != null) {
                dismissAllowingStateLoss();
            } else if (getActivity() != null) {
                getActivity().finish();
            }
        });
    }

    /**
     * 启动内容占位图
     */
    protected void setPlaceHolderTarget(View targetView) {
        if (mPlaceHolderView != null) {
            return;
        }
        mPlaceHolderView = new PlaceHolderView(getContext(), targetView);
    }


    /**
     * 获取内容占位图
     */
    protected PlaceHolderView getPlaceHolderView() {
        //默认contentView为操纵View
        if (mPlaceHolderView == null) {
            this.setPlaceHolderTarget(findViewById(R.id.basic_content_root));
        }
        return mPlaceHolderView;
    }

    protected void setContentView(View contentView) {
        this.contentView = contentView;
    }

    protected void setContentView(@LayoutRes int layoutId) {
        this.layoutId = layoutId;
    }

    public <T extends View> T findViewById(@IdRes int viewId) {
        if (getView() == null) {
            return null;
        }
        return getView().findViewById(viewId);
    }

    public void runOnUiThread(Runnable runnable) {
        FragmentActivity activity = getActivity();
        if (activity != null) {
            activity.runOnUiThread(runnable);
        }
    }


    public UIView getUIView() {
        return mUIView;
    }

    public int getWidth() {
        if (getView() == null) {
            return 0;
        }
        return getView().getMeasuredWidth();
    }

    public int getHeight() {
        if (getView() == null) {
            return 0;
        }
        return getView().getMeasuredHeight();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEventMainThread(EventData event) {
        this.onReceiveMessageEvent(event);
    }

    /**
     * 当接收到EventBus事件时会调用
     */
    protected void onReceiveMessageEvent(EventData event) {
    }


    //---------------------------------
    private float mDimAmount = 0.5f;//背景昏暗度
    private Direction direction;//dialog显示方向位置
    private int marginLeftRightDp = 30;//左右边距
    private int marginTopBottomDp = 30;//上下边距
    private int mAnimStyle;//进入退出动画
    private int widthDp = WindowManager.LayoutParams.WRAP_CONTENT;
    private int heightDp = WindowManager.LayoutParams.WRAP_CONTENT;

    //关闭DialogFragment时携带数据返回相关
    private OnDialogFragmentResult mOnDialogFragmentResult;
    private int requestCode;
    private int resultCode;
    private Intent resultData;


    @Override
    public void onStart() {
        super.onStart();
        this.initParams();
    }

    private void initParams() {
        if (getDialog() == null) {
            return;
        }
        Window window = getDialog().getWindow();
        if (window != null) {
            WindowManager.LayoutParams params = window.getAttributes();
            params.dimAmount = mDimAmount;

            //设置dialog显示位置
            if (direction != null) {
                switch (direction) {
                    case TOP:
                        params.gravity = Gravity.TOP;
                        break;
                    case BOTTOM:
                        params.gravity = Gravity.BOTTOM;
                        break;
                    case LEFT:
                        params.gravity = Gravity.START;
                        break;
                    case RIGHT:
                        params.gravity = Gravity.END;
                        break;
                }
            }

            //设置dialog宽度
            if (widthDp == 0) {
                params.width = ViewUtil.getScreenWidth() - 2 * DensityUtil.dp2px(marginLeftRightDp);
            } else if (widthDp == WindowManager.LayoutParams.WRAP_CONTENT
                    || widthDp == WindowManager.LayoutParams.MATCH_PARENT) {
                params.width = widthDp;
            } else {
                params.width = DensityUtil.dp2px(widthDp);
            }

            //设置dialog高度
            if (heightDp == 0) {
                params.height = ViewUtil.getScreenHeight() - 2 * DensityUtil.dp2px(marginTopBottomDp);
            } else if (heightDp == WindowManager.LayoutParams.WRAP_CONTENT
                    || heightDp == WindowManager.LayoutParams.MATCH_PARENT) {
                params.height = heightDp;
            } else {
                params.height = DensityUtil.dp2px(heightDp);
            }

            //设置dialog动画
            if (mAnimStyle != 0) {
                window.setWindowAnimations(mAnimStyle);
            }

            window.setAttributes(params);
        }
    }

    /**
     * 设置背景昏暗度
     *
     * @param level 黑色透明级别
     */
    public BasicDialogFragment setBackgroundBlackAlphaLevel(@FloatRange(from = 0, to = 1) float level) {
        mDimAmount = level;
        return this;
    }

    /**
     * 显示方向位置
     */
    public BasicDialogFragment setShowDirection(Direction direction) {
        this.direction = direction;
        return this;
    }

    /**
     * 设置宽高
     *
     * @param widthDp  以dp为单位的宽
     * @param heightDp 以dp为单位的高
     */
    public BasicDialogFragment setSize(int widthDp, int heightDp) {
        this.widthDp = widthDp;
        this.heightDp = heightDp;
        return this;
    }

    /**
     * 设置宽
     *
     * @param widthDp 以dp为单位的宽
     */
    public BasicDialogFragment setWidth(int widthDp) {
        this.widthDp = widthDp;
        return this;
    }

    /**
     * 设置高
     *
     * @param heightDp 以dp为单位的高
     */
    public BasicDialogFragment setHeight(int heightDp) {
        this.heightDp = heightDp;
        return this;
    }

    /**
     * 设置上下margin
     *
     * @param marginLeftRightDp 左右margin
     * @param marginTopBottomDp 上下margin
     */
    public BasicDialogFragment setMargin(int marginLeftRightDp, int marginTopBottomDp) {
        this.marginLeftRightDp = marginLeftRightDp;
        this.marginTopBottomDp = marginTopBottomDp;
        this.widthDp = 0;
        this.heightDp = 0;
        return this;
    }

    /**
     * 设置左右margin
     *
     * @param marginLeftRightDp 左右边距
     */
    public BasicDialogFragment setMarginLeftRight(int marginLeftRightDp) {
        this.marginLeftRightDp = marginLeftRightDp;
        this.widthDp = 0;
        return this;
    }

    /**
     * 设置上下margin
     *
     * @param marginTopBottomDp 上下边距
     */
    public BasicDialogFragment setMarginTopBottom(int marginTopBottomDp) {
        this.marginTopBottomDp = marginTopBottomDp;
        this.heightDp = 0;
        return this;
    }

    /**
     * 设置进入退出动画
     *
     * @param animStyle 动画样式资源id
     */
    public BasicDialogFragment setAnimStyle(@StyleRes int animStyle) {
        mAnimStyle = animStyle;
        return this;
    }

    /**
     * 设置是否点击外部取消
     *
     * @param outCancel 是否点击外部取消
     */
    public BasicDialogFragment setOutCancel(boolean outCancel) {
        super.setCancelable(outCancel);
        return this;
    }

    /**
     * 设置关闭时的回调监听
     */
    public BasicDialogFragment setOnDismissListener(DialogInterface.OnDismissListener onDismissListener) {
        this.mOnDismissListener = onDismissListener;
        return this;
    }

    /**
     * 设置关闭Dialog时携带数据回调
     */
    public BasicDialogFragment setOnDialogFragmentResult(OnDialogFragmentResult onDialogFragmentResult) {
        this.mOnDialogFragmentResult = onDialogFragmentResult;
        return this;
    }

    public void setResult(int resultCode) {
        this.setResult(resultCode, null);
    }

    public void setResult(int resultCode, Intent data) {
        this.resultCode = resultCode;
        this.resultData = data;
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);
        if (getParentFragment() != null) {
            getParentFragment().onHiddenChanged(false);
        }

        if (mOnDialogFragmentResult != null) {
            mOnDialogFragmentResult.onDialogFragmentResult(requestCode, resultCode, resultData);
        }

        if (mOnDismissListener != null) {
            mOnDismissListener.onDismiss(dialog);
        }
    }


    public BasicDialogFragment show(FragmentManager manager) {
        this.requestCode = 0;
        this.resultCode = 0;
        this.resultData = null;
        this.show(manager, String.valueOf(System.currentTimeMillis()));
        return this;
    }

    public BasicDialogFragment showForResult(FragmentManager manager, int requestCode) {
        this.requestCode = requestCode;
        this.show(manager, String.valueOf(System.currentTimeMillis()));
        return this;
    }

    @Override
    public void show(@NonNull FragmentManager manager, @Nullable String tag) {
        if (manager.isDestroyed()) {
            return;
        }
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, tag);
        ft.commitAllowingStateLoss();
    }

    /**
     * DialogFragment 关闭时携带数据回调
     */
    public interface OnDialogFragmentResult {

        /**
         * DialogFragment 关闭时携带数据返回上一个界面
         *
         * @param requestCode 请求码
         * @param resultCode  结果码
         * @param data        携带数据
         */
        void onDialogFragmentResult(int requestCode, int resultCode, @Nullable Intent data);

    }

    /**
     * 当前fragment对于用户可见或不可见时回调
     */
    protected void onUserVisible(boolean isVisible) {

    }
}
